// call(this：要指向的对象,剩余参数) 1. 执行函数   2.改变函数里面的 this  的 指向

function fn(a,b){
    return console.log(this,a+b)
}

const obj = {
    name:'邹希晨'
}
fn.call(obj,1,2) // { name: '邹希晨' } 3

let arr = [10,20,30]

console.log(arr.toString())  // Array.prototype  10,20,30 
console.log(obj.toString()) // Object.prototype  [object Object]

console.log(Object.prototype.toString.call(arr))//  [object Array]



// apply(this：要指向的对象,必须是数组，可以把原方法需要的参数全部放到数组中一起传入)
/**apply  与 call 的区别
 *  仅仅只是传参的方式不一样
 * 1.call  是以参数列表一个一个传进去的  
 * 2.apply  是传入一个数组
 */
fn.apply(obj,[10,20]) //  { name: '邹希晨' } 30

// 求数组最大值

console.log(Math.max(1,2,3))

const Array = [1,2,3,4,5]
console.log(Math.max.apply(null,Array)) // 5

// apply  被  ES6 的 ...展开运算符  代替
console.log(Math.max(...Array)) // 5



// bind(函数)  不会调用函数 ，而是返回一个新函数，新函数的  this  指向可以被修改
const newFn = fn.bind(obj)
newFn() // { name: '邹希晨' } NaN
 
// 应用场景  修改定时器的 this  指向
document.querySelector('button').addEventListener('click',function(){
   setTimeout(function(){
     this.style.color = 'red'
   }.bind(this),3000) // 这个 this  指向  button
})

// 可以用 箭头函数解决
document.querySelector('button').addEventListener('click',function(){
   setTimeout( ()=>{
    this.style.color = 'red'
   },3000)
 })